package org.wenhua.yuan.socket_server

import android.util.Log
import com.facebook.react.bridge.UiThreadUtil
import org.wenhua.yuan.socket_client.SocketClient2
import java.io.*
import java.net.ServerSocket
import java.net.Socket
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

/** SocketServer 服务端
 * 【测试提醒】使用注意事项：
 * 1，使用两台安卓真机
 * 2，须在同一wifi网络之下
 * 3，如果在同一个网络之下还是无法建立连接（如有报错如：System.err: java.net.NoRouteToHostException: Host unreachable）
 *    这种情况下，可以把两台手机都断开连接、断网，后重新连接同一WiFi。然后再进行客户端、服务端的连接。
 * 4，继续优化实现，参考使用  https://blog.csdn.net/ding3106/article/details/80714410
 * */
object SocketServer2 {

    private val TAG = SocketServer2::class.java.simpleName
    var result = true
    private const val SOCKET_PORT = 10000
    private var socket: Socket? = null
    private var serverSocket: ServerSocket? = null
    private lateinit var serverCallback: ServerCallback

    private val mList: ArrayList<Socket> = ArrayList<Socket>()
    private var bufferIn: BufferedReader? = null
    private var printWriter: PrintWriter? = null
    private var receiveMsg:String? = null

    // 服务端线程池
    private var serverThreadPool: ExecutorService? = null

    /** 开启服务 */
    fun startServer(callback: ServerCallback): Boolean {
        serverCallback = callback
        Thread {
            try {
                serverSocket = ServerSocket(SOCKET_PORT)
                while (result) {
                    Log.d("服务端进入while监听: ", "<<<执行accept()方法，且阻塞、监听>>>")
                    // 调用serverSocket的accept()方法，接收客户端发送的请求
                    socket = serverSocket?.accept()
                    Log.e("服务端进入while监听:", "服务器与客户端建立连接！！！")
                    serverCallback.onServerWarmingTip("server温馨提示：服务器与客户端建立连接！！！")
                    ServerThread(socket!!, serverCallback).start()
                }
            } catch (e: IOException) {
                Log.e("serverSocket-socket-IOException", e.toString())
                e.printStackTrace()
                result = false
            }
        }.start()
        return result
    }

    /** 关闭服务 */
    fun stopServer() {
        socket?.apply {
            shutdownInput()
            shutdownOutput()
            close()
        }
        serverSocket?.close()
        printWriter!!.close()
        bufferIn!!.close()
        //关闭线程池
        serverThreadPool?.shutdownNow()
        serverThreadPool = null
    }

    /** 发送到客户端 */
    fun sendToClient(msg: String) {
        if (serverThreadPool == null) {
            serverThreadPool = Executors.newCachedThreadPool()
        }
        serverThreadPool?.execute {
            if (socket == null) {
                serverCallback.onServerWarmingTip("server温馨提示：客户端还未连接")
                return@execute
            }
            if (socket!!.isClosed) {
                serverCallback.onServerWarmingTip("server温馨提示：Socket已关闭")
                return@execute
            }
            try {
                printWriter!!.println(msg)
            } catch (e: IOException) {
                e.printStackTrace()
                serverCallback.onServerWarmingTip("server温馨提示：向客户端发送${msg}失败")
            }
        }
    }

    /**
     * 回复心跳消息
     */
    fun replyHeartbeat() {
        if (serverThreadPool == null) {
            serverThreadPool = Executors.newCachedThreadPool()
        }
        val heartMessage = "[回复心跳消息：服务端，已收到！！！]"
        serverThreadPool?.execute {
            if (socket == null) {
                serverCallback.onServerWarmingTip("server温馨提示：客户端还未连接")
                return@execute
            }
            if (socket!!.isClosed) {
                serverCallback.onServerWarmingTip("server温馨提示：Socket已关闭")
                return@execute
            }
            try {
                printWriter!!.println(heartMessage) // 向客户端回复心跳信息
            } catch (e: IOException) {
                e.printStackTrace()
                serverCallback.onServerWarmingTip("server温馨提示：向客户端发送${heartMessage}失败")
            }
        }
    }

    class ServerThread(private val socket: Socket, private val serverCallback: ServerCallback) : Thread() {

        init {
            try {
                printWriter = PrintWriter(
                    BufferedWriter(
                        OutputStreamWriter(
                            socket.getOutputStream(),
                            "UTF-8"
                        )
                    ), true
                )
                bufferIn = BufferedReader(InputStreamReader(socket.getInputStream(), "UTF-8"))
            } catch (e: IOException) {
                e.printStackTrace()
            }

        }
        override fun run() {
            try {
                while (true) {                                   //循环接收、读取 Client 端发送过来的信息
                    if (bufferIn!!.readLine().also { receiveMsg = it } != null) {
                        System.out.println("服务端receiveMsg:$receiveMsg")
                        when (receiveMsg) {
                            "0" -> {
                                printWriter!!.println("服务器发送: 告知服务端已断开连接")
                                mList.remove(socket)
                                bufferIn!!.close()
                                socket.close() //接受 Client 端的断开连接请求，并关闭 Socket 连接
                            }
                            "=== 客户端已向服务端建立连接，正在发送心跳，收到请回复 ===" -> {
                                serverCallback.onHeartbeatClientMessage("连接已建立，并收到客户端发送的心跳 \n 服务端现已回复客户端心跳消息...")
                                printWriter!!.println("[回复心跳消息：服务端，已收到！！！]")
                            }
                            else -> UiThreadUtil.runOnUiThread(Runnable {
                                serverCallback.onReceiveClientMessage(
                                    socket.inetAddress.hostAddress,
                                    receiveMsg
                                )
                            })
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

}
